﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Kitware.VTK;

namespace HAVTKPack
{
   public class HydrolicGridGeometry:Geometry
   {

       #region 构造函数  目前使用第二个构造函数

        public HydrolicGridGeometry(HydrolicGrid hg)
       {
           this._hg = hg;    
       }

        public HydrolicGridGeometry(HydrolicGrid hg, List<int[,]> effectiveCellSign)
        {

            this._hg = hg;
            this.EffectiveSign1 = effectiveCellSign;
        }

        //public HydrolicGridGeometry(HydrolicGrid hg, List<int[,]> effectiveCellSign, List <double [,]> cellScalarValue)
        //{
        //   this._hg = hg;
        //    this.EffectiveSign1 = effectiveCellSign;

        //    this.CellScalarValue = cellScalarValue;
        //    //this.CellScalarValue = new List<double[,]>();
        //    //for (int i = 0; i < cellScalarValue.Count ; i++)
        //    //{
        //    //    this.CellScalarValue.Add((double [,])cellScalarValue [i].Clone ());
        //    //}

        //}


        #endregion


        #region  字段属性



        HydrolicGrid _hg;
        /// <summary>
        /// 不规则网格数据源
        /// </summary>
        public HydrolicGrid Hg
        {
            get { return _hg; }
            set
            {
                //当对象HydrolicGrid为null时，外围赋值不触发；当HydrolicGrid不为null时，外围赋值时触发
                //按照属性改变的规范写法  应该由判断是否改变的操作，但由于外围（例如参数设置界面）已经对
                //参数是否改变做了判断，改变则触发该事件，而且如果比较是否改变要涉及到double值比较，有潜在隐患
                //故此处不再进行比较操作

                //bool isChanged = false;
                //isChanged = IsHydrolicGridChanged.IsHyGridChanged(this._hg, value);
                //if (isChanged == true)
                //{
                    _hg = value;

                    this.OnHydrollicGridChanged();
                //}



            }
        }



        List<int[,]> EffectiveSign;
        /// <summary>
        /// 单元的有效性标记数组
        /// </summary>
        public List<int[,]> EffectiveSign1
        {
            get { return EffectiveSign; }
            set
            {
                //构造函数或外围赋值时 触发
                //是否改变的判断逻辑有外界（例如参数设置界面）完成，改变时触发该事件  故此处不做是否改变的判断，直接赋值

                //bool isChanged = false;
                //isChanged = IsEffectiveScalarSignChanged.IsCellSignChanged(this.EffectiveSign, value);
                //if (isChanged == true)
                //{
                    EffectiveSign = value;
                    this.OnEffectiveSign1Changed();
                //}


            }
        }




       // List<double[,]> cellScalarValue;
       ///// <summary>
       // /// 单元（体或者面）的scalar值
       ///// </summary>
       // public  List<double[,]> CellScalarValue
       // {
       //     get { return cellScalarValue; }
       //     set { 

       //         cellScalarValue = value;
       //         this.OnCellScalarValueChanged();
       //     }
       // }




        Vector scaleVector = new Vector(1, 1, 1);



        #endregion


   

       #region  VTK流水线所需对象


       //vtkTransform _transform;
       //public vtkTransform Transform
       //{
       //    get { return _transform; }
       //    set { _transform = value; }
       //}

      
       //vtkTransformPolyDataFilter _transFormPolyDataFilter;
  
       vtkTransformFilter _transFormFilter;
      
       vtkUnstructuredGrid unGrid;
       //[NonSerialized]
       vtkHexahedron hex2;
      
       //vtkConnectivityFilter con;
     
       //vtkGeometryFilter geo;

       vtkCellDataToPointData cTop;


       #endregion


       public override void Render()
       {

           unGrid = vtkUnstructuredGrid.New();
           hex2 = vtkHexahedron.New();

           //构造点 和 单元


           this.GetPointsAndCellArray();


           //cTop = vtkCellDataToPointData.New();

           //_transform = vtkTransform.New();
           if (this.GeometryTransform ==null )
           {
               this.GeometryTransform = vtkTransform.New();
           }

           this.GeometryTransform.Identity();
           this.GeometryTransform.Scale(this.scaleVector .X,this.scaleVector .Y,this.scaleVector .Z );


           _transFormFilter = vtkTransformFilter.New();



           //设置单元的 Scalar  值
    
           //this.SetCellScalarValue();
      
          


           ////该filter的输出类型是抽象类型使用方法GetPolyDataOutPut（）或者GetStructuredPointsOutPut（）得到你想要的数据

           //cTop.SetInput(unGrid);

           //。。。。。。。以下为2011.08.10。。。。修改


           //cTop.PassCellDataOn();

           _transFormFilter.SetTransform(this.GeometryTransform );
           //_transFormFilter.SetTransform(this._transform);
           _transFormFilter.SetInput(unGrid);
           //_transFormFilter.SetInput(cTop.GetOutput());


           //this._outPutData = this.unGrid;
           //this._outPutData = this.cTop.GetOutput();
           this._outPutData = this._transFormFilter.GetOutput();

           //。。。。。。。以上为2011.08.10。。。。修改

         



       }

       public override void StopRender()
       {

           //资源的销毁   资源的销毁应该是有顺序的吧   哈哈哈哈

           #region 普通字段属性的销毁

           if (this._hg != null)
           {
               //this._hg = null;
           }

           #endregion


           #region  VTK流水线的对象的销毁

           //dispose将所指向的地址的内容释放，谨慎使用  尤其是引用传递的

           if (this._transFormFilter != null)
           {
               this._transFormFilter.Dispose();
           }

           //if (this._transform != null)
           //{
           //    this._transform.Dispose();
           //}

           //if (_transFormPolyDataFilter != null)
           //{
           //    this._transFormPolyDataFilter.Dispose();
           //}




           if (this.hex2 != null)
           {
               this.hex2.Dispose();
           }

           if (this.unGrid != null)
           {
               this.unGrid.Dispose();
           }

           //if (this.con != null)
           //{
           //    this.con.Dispose();
           //}
           //if (this.geo != null)
           //{
           //    this.geo.Dispose();
           //}

           if (this.cTop !=null )
           {
               this.cTop.Dispose();
           }


           #endregion



       }


       #region 公有方法

       public void UpdateTransformScale(Vector newScaleVector)
       {
           //if (newScaleVector == null)
           //{
           //    return;
           //}

           //if (this.scaleVector == null)
           //{
           //    this.scaleVector = new Vector(1, 1, 1);
           //}


           this.scaleVector.X = newScaleVector.X;
           this.scaleVector.Y = newScaleVector.Y;
           this.scaleVector.Z = newScaleVector.Z;


           if (this.GeometryTransform != null)
           {
               this.GeometryTransform.Identity();
               this.GeometryTransform.Scale(this.scaleVector.X, this.scaleVector.Y, this.scaleVector.Z);

           }




       }



       #endregion



       #region  属性改变


       private void OnHydrollicGridChanged()
       {
           if (this._hg == null)
           {
               return;
           }

           this.SetPointsArray();
           //this.GetPointsAndCellArray();

       }

       private void OnEffectiveSign1Changed()
       {
           if (this.EffectiveSign == null)
           {
               return;
           }


           this.SetEffectiveCellArray();
           //this.GetPointsAndCellArray();

           ////this.OnCellScalarValueChanged();//Scalar

       }

       //private void OnCellScalarValueChanged()
       //{
       //    if (this.EffectiveSign == null )
       //    {
       //        return;
       //    }
       //    //if (this.scalar ==null )
       //    //{
       //    //    return;
       //    //}
       //    this.SetCellScalarValue();
       //}


       #endregion


       #region 内部方法





       /// <summary>
       /// 得到点集和单元集  构造网格
       /// </summary>
       private void GetPointsAndCellArray()
       {
           if (this.unGrid == null)
           {
               return;
           }


           #region 构造数据集的方式

           try
           {

               //this.SetPointAndCellArray();


               #region   将下面的代码分成了两个部分 分别进行实现操作


               int nLayer = this._hg.NLayers;
               int nCol = this._hg.NCols;
               int nRow = this._hg.NRows;
               int nPts = nLayer * nCol * nRow;






               #region 首先取得有效单元的个数

               int effectiveCellNumber = 0;


               for (int k = 0; k < nLayer - 1; k++)
               {
                   for (int i = 0; i < nRow - 1; i++)
                   {

                       for (int j = 0; j < nCol - 1; j++)
                       {

                           if (this.EffectiveSign1[k][i, j] != 0)
                           {
                               effectiveCellNumber = effectiveCellNumber + 1;

                           }
                       }
                   }
               }


               #endregion


               #region 如果有效单元的个数为0

               if (effectiveCellNumber <= 0)
               {
                 


                   vtkFloatArray array2 = vtkFloatArray.New();
                   array2.SetNumberOfComponents(3);
                   array2.SetNumberOfTuples(0);//点的个数？？

                   vtkPoints pts2 = vtkPoints.New();
                   pts2.SetData(array2);

                   vtkCellArray cellArray2 = vtkCellArray.New();
                   cellArray2.SetNumberOfCells(0);

                   unGrid.SetPoints(pts2);
                   unGrid.SetCells(hex2.GetCellType(), cellArray2);


                   return;

                 

               }


               #endregion


               #region 如果有效单元的个数不为0


               vtkFloatArray array = vtkFloatArray.New();
               array.SetNumberOfComponents(3);
               array.SetNumberOfTuples(nPts);

               #region  构造网格数据集

               int m = 0;

               Coordinate coord;

               for (int k = 0; k < nLayer; k++)
               {
                   for (int i = 0; i < nRow; i++)
                   {

                       for (int j = 0; j < nCol; j++)
                       {
                           coord = this._hg.Coords[i, j, k];
                           array.SetTuple3(m, coord.X, coord.Y, coord.Z);

                           m++;

                       }

                   }

               }

               vtkPoints pts = vtkPoints.New();
               pts.SetData(array);


             


               //单元格的个数
               int numCells = (nLayer - 1) * (nCol - 1) * (nRow - 1);

               vtkCellArray cellArray = vtkCellArray.New();

               //cellArray.InsertNextCell(8);


               vtkHexahedron hex = null;

               for (int k = 0; k < nLayer - 1; k++)
               {
                   for (int i = 0; i < nRow - 1; i++)
                   {
                       for (int j = 0; j < nCol - 1; j++)
                       {
                           int cc = k * nRow * nCol + i * nCol + j;

                            hex = vtkHexahedron.New();

                       
                           //构成一个单元格的8个点  注意顺序

                           hex.GetPointIds().SetId(0, (k + 1) * nRow * nCol + (i + 1) * nCol + j);
                           hex.GetPointIds().SetId(1, (k + 1) * nRow * nCol + (i + 1) * nCol + j + 1);
                           hex.GetPointIds().SetId(2, (k + 1) * nRow * nCol + i * nCol + j + 1);
                           hex.GetPointIds().SetId(3, (k + 1) * nRow * nCol + i * nCol + j);

                           hex.GetPointIds().SetId(4, k * nRow * nCol + (i + 1) * nCol + j);
                           hex.GetPointIds().SetId(5, k * nRow * nCol + (i + 1) * nCol + j + 1);
                           hex.GetPointIds().SetId(6, k * nRow * nCol + i * nCol + j + 1);
                           hex.GetPointIds().SetId(7, k * nRow * nCol + i * nCol + j);

                           if (this.EffectiveSign1[k][i, j] != 0)
                           {
                               cellArray.InsertNextCell(hex);

                           }
                           hex.Dispose();
                           hex = null;

                       }

                   }

               }

               #endregion

               unGrid.SetPoints(pts);
               unGrid.SetCells(hex2.GetCellType(), cellArray);


               //array.Dispose();//dispose将所指向的地址的内容释放，谨慎使用  尤其是引用传递的
               //pts.Dispose();
               //cellArray.Dispose();

               #endregion






            #endregion



           }
           catch (Exception)
           {

               System.Windows.Forms.MessageBox.Show("HydrolicGridGeometry构造网格过程出错！");

               return;

               //return 0;
           }

           #endregion

       }





       #region  Point Cell分别操作


       /// <summary>
       /// 设置点Points的信息
       /// </summary>
       private void SetPointsArray()
       {

           #region 进行了初步的优化  仅仅是提取设置Points部分


           if (this.unGrid == null)
           {
               return;
           }


           #region 构造数据集的方式

           try
           {
               //构造点  几何结构   不要关心Cell的有效性
          

               int nLayer = this._hg.NLayers;
               int nCol = this._hg.NCols;
               int nRow = this._hg.NRows;
               int nPts = nLayer * nCol * nRow;

      

               vtkFloatArray array = vtkFloatArray.New();
               array.SetNumberOfComponents(3);
               array.SetNumberOfTuples(nPts);

               int m = 0;

               Coordinate coord;

               for (int k = 0; k < nLayer; k++)
               {
                   for (int i = 0; i < nRow; i++)
                   {
                       for (int j = 0; j < nCol; j++)
                       {
                           coord = this._hg.Coords[i, j, k];

                           array.SetTuple3(m, coord.X, coord.Y, coord.Z);

                           m++;

                       }

                   }

               }

               vtkPoints pts = vtkPoints.New();
               pts.SetData(array);



               unGrid.SetPoints(pts);

               unGrid.Modified();





           }
           catch (Exception)
           {

               System.Windows.Forms.MessageBox.Show("HydrolicGridGeometry构造网格Points过程出错！");

               return;

               //return 0;
           }

           #endregion



           #endregion


       }



       /// <summary>
       /// 有效单元标志改变后重新设置 vtkUnstructuredGrid 的Cell
       /// </summary>
       private void SetEffectiveCellArray()
       {
           #region 进行了初步的优化  仅仅是提取设置Cell部分


           if (this.unGrid == null)
           {
               return;
           }

           try
           {

               //只改变Cell的构造方式  不要关心点的情况 


               int nLayer = this._hg.NLayers;
               int nCol = this._hg.NCols;
               int nRow = this._hg.NRows;
               int nPts = nLayer * nCol * nRow;


               #region 

               vtkCellArray cellArray = vtkCellArray.New();


               vtkHexahedron hex = null;

               for (int k = 0; k < nLayer - 1; k++)
               {
                   for (int i = 0; i < nRow - 1; i++)
                   {
                       for (int j = 0; j < nCol - 1; j++)
                       {

                           hex = vtkHexahedron.New();


                           //构成一个单元格的8个点  注意顺序

                           hex.GetPointIds().SetId(0, (k + 1) * nRow * nCol + (i + 1) * nCol + j);
                           hex.GetPointIds().SetId(1, (k + 1) * nRow * nCol + (i + 1) * nCol + j + 1);
                           hex.GetPointIds().SetId(2, (k + 1) * nRow * nCol + i * nCol + j + 1);
                           hex.GetPointIds().SetId(3, (k + 1) * nRow * nCol + i * nCol + j);

                           hex.GetPointIds().SetId(4, k * nRow * nCol + (i + 1) * nCol + j);
                           hex.GetPointIds().SetId(5, k * nRow * nCol + (i + 1) * nCol + j + 1);
                           hex.GetPointIds().SetId(6, k * nRow * nCol + i * nCol + j + 1);
                           hex.GetPointIds().SetId(7, k * nRow * nCol + i * nCol + j);

                           if (this.EffectiveSign1[k][i, j] != 0)
                           {
                               cellArray.InsertNextCell(hex);

                           }
                           hex.Dispose();
                           hex = null;

                       }

                   }

               }

               #endregion

  
               unGrid.SetCells(hex2.GetCellType(), cellArray);


               unGrid .Modified();



           }
           catch (Exception)
           {

               System.Windows.Forms.MessageBox.Show("HydrolicGridGeometry构造网格Cell过程出错！");

               return;

               //return 0;
           }


           #endregion



       }


       /// <summary>
       /// 未调通  未调用    同时改变Ponts和Cell设置  向合并大量for循环以提高效率
       /// </summary>
       private void SetPointAndCellArray()
       {

           if (this.unGrid == null)
           {
               return;
           }


           #region 构造数据集的方式

           try
           {




               int nLayer = this._hg.NLayers;
               int nCol = this._hg.NCols;
               int nRow = this._hg.NRows;
               int nPts = nLayer * nCol * nRow;



               int effectiveCellNumber = 0;



               #region 如果有效单元的个数不为0


               vtkFloatArray array = vtkFloatArray.New();

               array.SetNumberOfComponents(3);



               vtkCellArray cellArray = vtkCellArray.New();


               #region  构造网格数据集

               int m = 0;

               Coordinate coord;

               for (int k = 0; k < nLayer; k++)
               {
                   for (int i = 0; i < nRow; i++)
                   {
                       for (int j = 0; j < nCol; j++)
                       {

                           coord = this._hg.Coords[i, j, k];

                           array.InsertNextTuple4(m, coord.X, coord.Y, coord.Z);

                           m++;

                           if (k <= nLayer - 2)
                           {
                               if (i <= nRow - 2)
                               {
                                   if (j <= nCol - 2)
                                   {
                                       vtkHexahedron hex = vtkHexahedron.New();

                                       //构成一个单元格的8个点  注意顺序

                                       hex.GetPointIds().SetId(0, (k + 1) * nRow * nCol + (i + 1) * nCol + j);
                                       hex.GetPointIds().SetId(1, (k + 1) * nRow * nCol + (i + 1) * nCol + j + 1);
                                       hex.GetPointIds().SetId(2, (k + 1) * nRow * nCol + i * nCol + j + 1);
                                       hex.GetPointIds().SetId(3, (k + 1) * nRow * nCol + i * nCol + j);

                                       hex.GetPointIds().SetId(4, k * nRow * nCol + (i + 1) * nCol + j);
                                       hex.GetPointIds().SetId(5, k * nRow * nCol + (i + 1) * nCol + j + 1);
                                       hex.GetPointIds().SetId(6, k * nRow * nCol + i * nCol + j + 1);
                                       hex.GetPointIds().SetId(7, k * nRow * nCol + i * nCol + j);




                                       //            hex.GetPointIds().SetId(0, (k + 1) * nRow * nCol + (i + 1) * nCol + j);
                                       //            hex.GetPointIds().SetId(1, (k + 1) * nRow * nCol + (i + 1) * nCol + j + 1);
                                       //            hex.GetPointIds().SetId(2, (k + 1) * nRow * nCol + i * nCol + j + 1);
                                       //            hex.GetPointIds().SetId(3, (k + 1) * nRow * nCol + i * nCol + j);

                                       //            hex.GetPointIds().SetId(4, k * nRow * nCol + (i + 1) * nCol + j);
                                       //            hex.GetPointIds().SetId(5, k * nRow * nCol + (i + 1) * nCol + j + 1);
                                       //            hex.GetPointIds().SetId(6, k * nRow * nCol + i * nCol + j + 1);
                                       //            hex.GetPointIds().SetId(7, k * nRow * nCol + i * nCol + j);






                                       if (this.EffectiveSign1[k][i, j] != 0)
                                       {
                                           effectiveCellNumber = effectiveCellNumber + 1;

                                           cellArray.InsertNextCell(hex);
                                       }
                                       hex.Dispose();

                                   }
                               }
                           }
                       }
                   }
               }
               //cellArray.SetNumberOfCells(effectiveCellNumber);
               //if (effectiveCellNumber > 0)
               //{
               //    array.SetNumberOfTuples(nPts);
               //}
               //if (effectiveCellNumber == 0)
               //{
               //    array.SetNumberOfTuples(0);
               //}

               vtkPoints pts = vtkPoints.New();
               pts.SetData(array);



               #endregion

               unGrid.SetPoints(pts);


               unGrid.SetCells(hex2.GetCellType(), cellArray);



               #endregion




           }
           catch (Exception)
           {

               System.Windows.Forms.MessageBox.Show("HydrolicGridGeometry构造网格过程出错！");

               return;

               //return 0;
           }


           #endregion

       }





       #endregion




       #endregion





   }
}
